/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file  Can.h
 * @brief Semidrive. AUTOSAR 4.3.1 MCAL Can Driver.
 */
#ifndef CAN_H_
#define CAN_H_

#include "Mcal.h"
#include "ComStack_Types.h"
#include "Can_Cfg.h"
#include "Can_GeneralTypes.h"
#include "Mcal_ScrBits.h"
#include "Mcal_Scr.h"
#include "Part.h"

/* Version and Check Begin */
/* Version Info Begin */
#define CAN_H_VENDOR_ID    0x8C
#define CAN_H_AR_RELEASE_MAJOR_VERSION    4
#define CAN_H_AR_RELEASE_MINOR_VERSION    3
#define CAN_H_AR_RELEASE_REVISION_VERSION 1
#define CAN_H_SW_MAJOR_VERSION    1
#define CAN_H_SW_MINOR_VERSION    0
#define CAN_H_SW_PATCH_VERSION    0
/* Version Info End */

/* Version Check Begin */
#if !defined(DISABLE_MCAL_ASR_VER_CHECK)
#if ((CAN_H_AR_RELEASE_MAJOR_VERSION != MCAL_H_AR_RELEASE_MAJOR_VERSION)\
    || (CAN_H_AR_RELEASE_MINOR_VERSION != MCAL_H_AR_RELEASE_MINOR_VERSION)\
    || (CAN_H_AR_RELEASE_REVISION_VERSION != MCAL_H_AR_RELEASE_REVISION_VERSION))
#error "Opps, Can.h and Mcal.h AutoSAR version not match!"
#endif
#endif  /* !DISABLE_MCAL_ASR_VER_CHECK */
#if !defined(DISABLE_MCAL_SW_VER_CHECK)
#if ((CAN_H_SW_MAJOR_VERSION != MCAL_H_SW_MAJOR_VERSION)\
    || (CAN_H_SW_MINOR_VERSION != MCAL_H_SW_MINOR_VERSION)\
    || (CAN_H_SW_PATCH_VERSION != MCAL_H_SW_PATCH_VERSION))
#error "Opps, Can.h and Mcal.h Software version not match!"
#endif
#endif  /* !DISABLE_MCAL_SW_VER_CHECK */
#if !defined(DISABLE_MCAL_ASR_VER_CHECK)
#if ((CAN_H_AR_RELEASE_MAJOR_VERSION != COMSTACK_TYPES_H_AR_RELEASE_MAJOR_VERSION)\
    || (CAN_H_AR_RELEASE_MINOR_VERSION != COMSTACK_TYPES_H_AR_RELEASE_MINOR_VERSION)\
    || (CAN_H_AR_RELEASE_REVISION_VERSION != COMSTACK_TYPES_H_AR_RELEASE_REVISION_VERSION))
#error "Opps, Can.h and ComStack_Types.h AutoSAR version not match!"
#endif
#endif  /* !DISABLE_MCAL_ASR_VER_CHECK */
#if !defined(DISABLE_MCAL_SW_VER_CHECK)
#if ((CAN_H_SW_MAJOR_VERSION != COMSTACK_TYPES_H_SW_MAJOR_VERSION)\
    || (CAN_H_SW_MINOR_VERSION != COMSTACK_TYPES_H_SW_MINOR_VERSION)\
    || (CAN_H_SW_PATCH_VERSION != COMSTACK_TYPES_H_SW_PATCH_VERSION))
#error "Opps, Can.h and ComStack_Types.h Software version not match!"
#endif
#endif  /* !DISABLE_MCAL_SW_VER_CHECK */
#if !defined(DISABLE_MCAL_ASR_VER_CHECK)
#if ((CAN_H_AR_RELEASE_MAJOR_VERSION != CAN_GENERALTYPES_H_AR_RELEASE_MAJOR_VERSION)\
    || (CAN_H_AR_RELEASE_MINOR_VERSION != CAN_GENERALTYPES_H_AR_RELEASE_MINOR_VERSION)\
    || (CAN_H_AR_RELEASE_REVISION_VERSION != CAN_GENERALTYPES_H_AR_RELEASE_REVISION_VERSION))
#error "Opps, Can.h and Can_GeneralTypes.h AutoSAR version not match!"
#endif
#endif  /* !DISABLE_MCAL_ASR_VER_CHECK */
#if !defined(DISABLE_MCAL_SW_VER_CHECK)
#if ((CAN_H_SW_MAJOR_VERSION != CAN_GENERALTYPES_H_SW_MAJOR_VERSION)\
    || (CAN_H_SW_MINOR_VERSION != CAN_GENERALTYPES_H_SW_MINOR_VERSION)\
    || (CAN_H_SW_PATCH_VERSION != CAN_GENERALTYPES_H_SW_PATCH_VERSION))
#error "Opps, Can.h and Can_GeneralTypes.h Software version not match!"
#endif
#endif  /* !DISABLE_MCAL_SW_VER_CHECK */
/* Version Check End */
/* Version and Check End */

#ifdef __cplusplus
extern "C" {
#endif

/* Module version definition. */
#define CAN_VENDOR_ID                   0x8C
#define CAN_MODULE_ID                   80
#define CAN_AR_RELEASE_MAJOR_VERSION    4
#define CAN_AR_RELEASE_MINOR_VERSION    3
#define CAN_AR_RELEASE_REVISION_VERSION 1
#define CAN_SW_MAJOR_VERSION            1
#define CAN_SW_MINOR_VERSION            0
#define CAN_SW_PATCH_VERSION            0

/**
* @brief Development errors.
*/
#define CAN_E_PARAM_POINTER      ((uint8)0x01U)
#define CAN_E_PARAM_HANDLE       ((uint8)0x02U)
#define CAN_E_PARAM_DATA_LENGTH  ((uint8)0x03U)
#define CAN_E_PARAM_CONTROLLER   ((uint8)0x04U)
#define CAN_E_UNINIT             ((uint8)0x05U)
#define CAN_E_TRANSITION         ((uint8)0x06U)
#define CAN_E_PARAM_BAUDRATE      ((uint8)0x07U)
#define CAN_E_ICOM_CONFIG_INVALID ((uint8)0x08U)
#define CAN_E_INIT_FAILED         ((uint8)0x09U)
#define CAN_E_DATALOST            ((uint8)0x01U)
#define CAN_E_INVALID_CONTROLLER ((uint8)0x0AU)
#define CAN_E_TIMEOUT            ((uint8)0x0BU)

/**
* @brief Service ID (APIs) for Det reporting.
*/
#define CAN_SID_INIT                          ((uint8)0x00U)
#define CAN_SID_MAIN_FUNCTION_WRITE           ((uint8)0x01U)
#define CAN_SID_SET_CONTROLLER_MODE           ((uint8)0x03U)
#define CAN_SID_DISABLE_CONTROLLER_INTERRUPTS ((uint8)0x04U)
#define CAN_SID_ENABLE_CONTROLLER_INTERRUPTS  ((uint8)0x05U)
#define CAN_SID_WRITE                         ((uint8)0x06U)
#define CAN_SID_GET_VERSION_INFO              ((uint8)0x07U)
#define CAN_SID_MAIN_FUNCTION_READ            ((uint8)0x08U)
#define CAN_SID_MAIN_FUNCTION_BUS_OFF         ((uint8)0x09U)
#define CAN_SID_MAIN_FUNCTION_WAKEUP          ((uint8)0x0AU)
#define CAN_SID_CBK_CHECK_WAKEUP              ((uint8)0x0BU)
#define CAN_SID_MAIN_FUNCTION_MODE            ((uint8)0x0CU)
#define CAN_SID_CHANGE_BAUDRATE               ((uint8)0x0DU)
#define CAN_SID_CHECK_BAUDRATE                ((uint8)0x0EU)
#define CAN_SID_SET_BAUDRATE                  ((uint8)0x0FU)
#define CAN_SID_DEINIT                        ((uint8)0x10U)
#define CAN_SID_GETCONTROLLERERRORSTATE       ((uint8)0x11U)
#define CAN_SID_GETCONTROLLERMODE             ((uint8)0x12U)
#define CAN_SID_IP_ENABLE                     ((uint8)0x13U)
#define CAN_SID_IP_DISABLE                    ((uint8)0x14U)
#define CAN_SID_IP_RESET                      ((uint8)0x15U)
#define CAN_SID_IP_LOWPOER                    ((uint8)0x16U)
#define CAN_SID_GET_CONTROLLER_RX_ERROR_COUNTER   ((uint8)0x17U)
#define CAN_SID_GET_CONTROLLER_TX_ERROR_COUNTER   ((uint8)0x18U)
#define CAN_SID_VCAN_TX_RX_FIFO_GET_ABNORMAL_NUM  ((uint8)0x19U)

/**
* @brief Can busy.
*/
#define        CAN_BUSY  (2U)

/**
 * @brief Frmae ID parsing in PduInfo.
 */
#define CAN_FD_ID_MASK  (0x40000000U)
#define CAN_EXTENDED_ID_MASK   (0x80000000U)
#define CAN_ID_MASK (0x3FFFFFFFU)

/** \brief Cache line length are 64 bytes */
#define CAN_CONFIG_ARCH_CACHE_LINE    CACHE_SIZE

/**
 * @brief The maxium number of Message Buffers in each controller.
 */
/* Only 128 mailboxs, and the last one is used to enhanced FIFO mark. */
#define FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER 128U
#define FLEXCAN_ENHANCED_FIFO_NUMBER          1U

/* Number of message buffer region. */
#if FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER <= 32
#define REGION_NUM  1U
#elif FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER <= 64
#define REGION_NUM  2U
#elif FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER <= 96
#define REGION_NUM  3U
#elif FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER <= 128
#define REGION_NUM  4U
#else
#error "There is no additional region here"
#endif

/** \brief  Numeric identifier of Core Id. */
typedef uint8 Can_CoreIdType;

/**
 * @brief States of CAN driver state machine.
 */
typedef enum
{
    CAN_UNINIT = 0U,
    CAN_READY,
    CAN_SUSPEND
} Can_DriverStateType;

/**
 * @brief CAN event, such as Rx/Tx frame, wakeup, etc., processing mode.
 */
typedef enum
{
    INTERRUPT = 0U,
    POLLING,
    MIXED
} Can_EventProcessingType;

/**
 * @brief CAN ID type.
 */
typedef enum
{
    CAN_ID_STANDARD = 0U,
    CAN_ID_EXTENDED,
    CAN_ID_MIXED
} Can_IdTypeType;

/**
 * @brief Hardware object type.
 */
typedef enum
{
    RECEIVE = 0U,
    TRANSMIT,
    UNUSED_MB
} Can_HohTypeType;

/**
 * @brief Rx FIFO ID filter table format.
 */
typedef enum
{
    RX_FIFO_FILTER_TYPE_A = 0U,
    RX_FIFO_FILTER_TYPE_B,
    RX_FIFO_FILTER_TYPE_C,
    RX_FIFO_FILTER_TYPE_D,
    /* Rx Enhanced FIFO ID filter table format. */
    RX_FIFO_MASK_FILTER_SCHEME,
    RX_FIFO_RANGE_FILTER_SCHEME,
    RX_FIFO_TWO_FILTER_SCHEME
} Can_RxFIFOFilterTableFormatType;

/**
 * @brief Rx FIFO reception priority type.
 */
typedef enum
{
    MB_PRIORITY_LOW = 0U,
    MB_PRIORITY_HIGH
} Can_MBRxPriorityType;

/**
 * @brief CAN controller interrupt mask structure.
 */
typedef struct
{
    uint32 errIntMask;
    uint32 wakeUpIntMask;
    uint32 mb_0_31_IntMask;
    uint32 mb_32_63_IntMask;
    uint32 mb_64_95_IntMask;
    uint32 mb_96_127_IntMask;
#if (CAN_ENHANCED_FIFO_SUPPORT == STD_ON)
    uint32 enhFifoInterrupts;
#endif /** #if (CAN_ENHANCED_FIFO_SUPPORT == STD_ON) */
} Can_ControllerIntMaskType;

/**
 * @brief MB type: Rx or Tx.
 */
typedef enum
{
    MB_UNUSED = 0U,
    MB_RX,
    MB_TX
} Can_MBTypeType;

/**
 * @brief MB state.
 */
typedef enum
{
    MB_IDLE = 0U,
    MB_BUSY
} Can_MBStateType;

/**
 * @brief MB information structure.
 */
typedef struct
{
    uint16 hwObjId;
    PduIdType canIfPduId;
    Can_MBTypeType mbType;
    Can_MBStateType mbState;
} Can_MBInfoType;

/**
 * @brief CAN controller information structure.
 */
typedef struct
{
    Can_ControllerIntMaskType intMask;
    Can_MBInfoType mbInfo[FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER + FLEXCAN_ENHANCED_FIFO_NUMBER];
    uint16 pollingMBConfigIndex[FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBER + FLEXCAN_ENHANCED_FIFO_NUMBER];
    uint8 pollingMBNum;
    uint8 firstTxPollingMBPos;
    boolean rxFifoUsePolling;
#if (CAN_MULTIPLE_READ_PERIOD == STD_ON)
    uint8 rxFifoPollingPeriodId;
#endif
} Can_ControllerInfoType;

/**
 * @brief VCAN controller information structure.
 */
typedef struct
{
    Can_MBInfoType mbInfo[2];
} VCan_ControllerInfoType;

/**
 * @brief Rx frame structure.
 */
typedef struct
{
    Can_IdType id;
    uint8 data[64];
    uint8 length;
} Can_RxFrameType;

/**
 * @brief CAN stop/doze bits in SCR.
 */
typedef struct
{
    uint32 can_addr;
    Mcal_ScrSignalType can_scr;
} Can_ScrBitsType;

/**
 * @brief CAN sleep mode type.
 */
typedef enum
{
    DOZE_MODE = 0U,
    STOP_MODE
} Can_SleepModeType;

/**
 * @brief Can Bit Rate.
 */
typedef struct
{
    /* Prescaler Devider */
    const uint16 prescaler;
    /* Propagation Segment */
    const uint8 propSeg;
    /* Phase Segment 1 */
    const uint8 phaseSeg1;
    /* Phase Segment 2 */
    const uint8 phaseSeg2;
    /* Synchronization Jump Width*/
    const uint8 resyncJumpWidth;
} Can_TimeSegmentType;

#if (CAN_FD_SUPPORT == STD_ON)
/**
 * @brief CAN FD configuration structure.
 */
typedef struct
{
    /* CAN FD basic configuration,
     * bit0: CANFD, bit1: ISO-CANFD, bit2: TxBRS.
     */
    const uint8 option;
    const uint8 tdcOffset;
    const Can_TimeSegmentType dataBitTimingRegAlt;
} Can_FDConfigType;
#endif

/**
 * @brief Baud rate configuration structure.
 */
typedef struct
{
    const uint16 baudRateConfigId;
    const uint16 extendBitTimingFormat;
    const uint16 enhancedBitTimingFormat;
    const Can_TimeSegmentType nominalBitTimingRegAlt;
#if (CAN_FD_SUPPORT == STD_ON)
    const Can_FDConfigType fdConfig;
#endif
} Can_BaudRateConfigType;

/**
 * @brief CAN controller configuration structure.
 */
typedef struct
{
    /**< Contoller is used=1 or not_used=0*/
    boolean controllerActive;
    uint32 baseAddr;
    Can_EventProcessingType rxProcType;
    Can_EventProcessingType txProcType;
    Can_EventProcessingType busoffProcType;
    Can_EventProcessingType wakeupProcType;
    uint8 controllerId;
    uint8 maxMBNum;
    /* Basic configuration,
     * bit0: LoopBack, bit1: ListeOnly, bit2: SelfWakeUp, bit3: PEClockFromOsc,
     * bit4: IndividualRxMask, bit5: DozeMode, bit6: RxFIFO, bit7: LowestNumberMBFirst,
     * bit8: EnhancedRxFIFO.
     */
    uint32 option;
#if (CAN_CHECK_WAKEUP_API == STD_ON)
    boolean wakeupEnable;
#endif
    uint16 defaultBaudRateId;
    uint16 baudRateConfigCount;
    const Can_BaudRateConfigType *baudRateConfig;
#if (CAN_FD_SUPPORT == STD_ON)
    uint32 mbdsrVal;
#endif
    Can_RxFIFOFilterTableFormatType rxFifoFilterTableFormat;
    Can_MBRxPriorityType mbPriority;
    /** Module Core Id*/
    Can_CoreIdType coreId;
} Can_ControllerConfigType;

/**
 * @brief MB configuration structure.
 */
typedef struct
{
    Can_IdTypeType idType;
    Can_HohTypeType hohType;
    uint16 canObjId;
    uint8 controllerId;
    uint8 mbId;
    uint8 payloadSize;
    uint8 fdPaddingVal;
    boolean usePolling;
#if (CAN_MULTIPLE_READ_PERIOD == STD_ON) || (CAN_MULTIPLE_WRITE_PERIOD == STD_ON)
    uint8 pollingPeriodId;
#endif
#if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
    boolean triggerTransmitEnable;
#endif
    uint32 filterCode;
    uint32 filterMask;
} Can_MBConfigType;

/**
 * @brief Rx FIFO filter table structure.
 */
typedef struct
{
    uint32 filterCode;
    uint32 filterMask;
} Can_RxFIFOFilterTableType;

/**
 * @brief Rx FIFO configuration structure.
 */
typedef struct
{
    Can_IdTypeType idType;
    uint16 canObjId;
    uint8 controllerId;
    boolean usePolling;
#if (CAN_MULTIPLE_READ_PERIOD == STD_ON)
    uint8 pollingPeriodId;
#endif
    /* Number of MB used by Rx FIFO must be in the range [8, ControllerConfig.maxMBNum],
     * and must be even.
     */
    uint8 usedMBNum;
    /* Number of filter code must not be more than usedMBNum. */
    uint8 fliterCodeNum;
#if (CAN_ENHANCED_FIFO_SUPPORT == STD_ON)
    /* Enhanced FIFO filter elements number. */
    uint8 standardFilterNum;
    uint8 extendedFilterNum;
    uint8 watermarkLevel;
#endif /** #if (CAN_ENHANCED_FIFO_SUPPORT == STD_ON) */
    /* Pointer to the array of Rx FIFO filter table. */
    const Can_RxFIFOFilterTableType *filterTable;
    boolean usedDpe;
} Can_RxFifoConfigType;

typedef struct
{
    uint32 *vcanTxFifo;
    uint32 *vcanRxFifo;
} VCan_FifoConfigType;

typedef struct
{
    uint32 vcanRecDropNum;
    uint32 vcanSendTimeoutNum;
    uint32 vcanSendFlushNum;
    uint32 vcanSendFilteredNum;
    uint32 vcanSendReplacedNum;
    uint32 vcanSendUnexpectedNum;
    uint32 vcanSendStatusInvalidNum;
} VCan_TxRxAbnormalNumType;

typedef struct
{
    /**< Contoller is used=1 or not_used=0*/
    boolean controllerActive;
    uint32 dpeBase;
    uint16 vcanControllerId;
    boolean enableDrop;
    const VCan_FifoConfigType *vcanFifoConfig;
    Can_EventProcessingType rxProcType;
    Can_EventProcessingType txProcType;
    uint32 intMask;
#if (CAN_CHECK_WAKEUP_API == STD_ON)
    boolean wakeupEnable;
#endif
    /** Module Core Id*/
    Can_CoreIdType coreId;
} VCan_ControllerConfigType;

/**
 * @brief CAN configuration structure.
 */
typedef struct
{
    /* Pointer to the array of all canfd controller configurations. */
    const Can_ControllerConfigType *controllerConfig;
    /* Pointer to the array of all MBs. */
    const Can_MBConfigType *mbConfig;
    /* Pointer to the array of all Rx FIFOs. */
    const Can_RxFifoConfigType *rxFifoConfig;
    /* All Rx MBs are ahead of all Tx MBs. */
    uint16 firstHthIndex;
    /* Pointer to the array of all vcan controller configurations. */
    const VCan_ControllerConfigType *vcanControllerConfig;
} Can_ConfigType;

extern CONST(Can_ConfigType, CAN_VAR) Can_Config;

typedef struct
{
    /** Can configure pointer */
    const Can_ConfigType *configPtr;
#if (defined(AUTOSAR_VERSION_421)) || (defined(AUTOSAR_VERSION_403))
    Can_StateTransitionType Can_gControllerState[32];
#else
    Can_ControllerStateType Can_gControllerState[32];
#endif
    Can_DriverStateType Can_gCanDriverState;
    uint16 Can_gu16CurBaudRateConfigId[16];
    uint8 Can_gu8ControllerIntsDisableCnt[32];
    uint8 g_eControllerBusoffState[32];
    Can_ControllerInfoType g_CanControllerInfo[16];
#if (VCAN_ENABLE == STD_ON)
    VCan_ControllerInfoType g_VCanControllerInfo[16];
    uint32 g_VCanTxIndex[16];
    VCan_TxRxAbnormalNumType g_VCanTxRxAbnormalNum[16];
#endif/*end of VCAN_ENABLE*/
} Can_HandlerConfigType LOCATE_ALIGNED(CAN_CONFIG_ARCH_CACHE_LINE);


#if (CAN_VERSION_INFO_API == STD_ON)
/**
 * @brief Get version information of CAN driver.
 * @param versioninfo Output version information.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_GetVersionInfo
(
    P2VAR(Std_VersionInfoType, AUTOMATIC, CAN_APPL_DATA) versioninfo
);
#endif

/**
 * @brief Initialize all configured CAN controllers.
 * @param Config Pointer to CAN configuration.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_Init
(
    P2CONST(Can_ConfigType, AUTOMATIC, CAN_APPL_CONST) Config
);

/**
 * @brief De-initialize all configured controllers.
 * @param void no paramter.
 * @return none.
 */
#if (!defined(AUTOSAR_VERSION_421)) && (!defined(AUTOSAR_VERSION_403))
extern FUNC(void, CAN_CODE) Can_DeInit(void);
#endif

#if (CAN_SET_BAUDRATE_API == STD_ON)
/**
 * @brief Set baud rate of the controller.
 * @param Controller CAN controller ID.
 * @param BaudRateConfigID Baud rate configuration ID.
 * @return Baud rate setting result.
 *  @retval E_OK Set baud rate successfully.
 *  @retval E_NOT_OK Set baud rate failed.
 */
extern FUNC(Std_ReturnType, CAN_CODE) Can_SetBaudrate
(
    VAR(uint8, AUTOMATIC) Controller,
    VAR(uint16, AUTOMATIC) BaudRateConfigID
);
#endif

/**
 * @brief Trigger state transition of the CAN controller state machine.
 * @param Controller CAN controller ID.
 * @param Transition New CAN controller state.
 * @return State setting result.
 *  @retval E_OK State transimitted successfully.
 *  @retval E_NOT_OK State transimitted failed.
 */
#if (defined(AUTOSAR_VERSION_421)) || (defined(AUTOSAR_VERSION_403))
extern FUNC(Std_ReturnType, CAN_CODE) Can_SetControllerMode
(
    VAR(uint8, AUTOMATIC) Controller,
    VAR(Can_StateTransitionType, AUTOMATIC) Transition
);
#else
extern FUNC(Std_ReturnType, CAN_CODE) Can_SetControllerMode
(
    VAR(uint8, AUTOMATIC) Controller,
    VAR(Can_ControllerStateType, AUTOMATIC) Transition
);
#endif

/**
 * @brief Disable controller interrupts.
 * @param Controller Controller ID.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_DisableControllerInterrupts
(
    VAR(uint8, AUTOMATIC) Controller
);

/**
 * @brief Enable controller interrupts.
 * @param Controller Controller ID.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_EnableControllerInterrupts
(
    VAR(uint8, AUTOMATIC) Controller
);

#if (CAN_CHECK_WAKEUP_API == STD_ON)
/**
 * @brief Check if a wakeup has occured for the controller.
 * @param Controller Controller ID.
 * @return API calling result.
 *  @retval E_OK Wakeup is detected.
 *  @retval E_NOT_OK Wakeup is not detected.
 */
extern FUNC(Std_ReturnType, CAN_CODE) Can_CheckWakeup
(
    VAR(uint8, AUTOMATIC) Controller
);
#endif

/**
 * @brief Get error state of the controller.
 * @param ControllerId Controller ID.
 * @param ErrorStatePtr Ouput error state.
 * @return API calling result.
 *  @retval E_OK Call API successfully.
 *  @retval E_NOT_OK Call API failed.
 */
extern FUNC(Std_ReturnType, CAN_CODE) Can_GetControllerErrorState
(
    VAR(uint8, AUTOMATIC) ControllerId,
    P2VAR(Can_ErrorStateType, AUTOMATIC, CAN_APPL_DATA) ErrorStatePtr
);

/**
 * @brief Get the current state of the controller.
 * @param Controller Controller ID.
 * @param ControllerModePtr Output the current state.
 * @return API calling result.
 *  @retval E_OK Call API successfully.
 *  @retval E_NOT_OK Call API failed.
 */
#if (defined(AUTOSAR_VERSION_421)) || (defined(AUTOSAR_VERSION_403))
extern FUNC(Std_ReturnType, CAN_CODE) Can_GetControllerMode
(
    VAR(uint8, AUTOMATIC) Controller,
    P2VAR(Can_StateTransitionType, AUTOMATIC, CAN_APPL_DATA) ControllerModePtr
);
#else
extern FUNC(Std_ReturnType, CAN_CODE) Can_GetControllerMode
(
    VAR(uint8, AUTOMATIC) Controller,
    P2VAR(Can_ControllerStateType, AUTOMATIC, CAN_APPL_DATA) ControllerModePtr
);
#endif

/**
 * @brief Transmit a CAN message.
 * @param Hth Hardware-transmit handle.
 * @param PduInfo Pointer to SDU user memory, data length and identifier.
 * @return API calling result.
 *  @retval E_OK Write CAN MB successfully.
 *  @retval E_NOT_OK Write CAN MB failed.
 */
extern FUNC(Std_ReturnType, CAN_CODE) Can_Write
(
    VAR(Can_HwHandleType, AUTOMATIC) Hth,
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_DATA) PduInfo
);

/**
 * @brief Polling of Tx confirmation.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write(void);

/**
 * @brief Polling of Rx indication.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read(void);

#if (CAN_MULTIPLE_WRITE_PERIOD == STD_ON)
#if (CAN_MAINFUNCTION_RW_PERIOD_0 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 0.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_0(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_1 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 1.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_1(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_2 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 2.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_2(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_3 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 3.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_3(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_4 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 4.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_4(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_5 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 5.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_5(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_6 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 6.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_6(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_7 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 7.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_7(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_8 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 8.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_8(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_9 != STD_OFF)
/**
 * @brief Polling of Tx confirmation at period 9.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Write_9(void);
#endif
#endif /* CAN_MULTIPLE_WRITE_PERIOD == STD_ON */

#if (CAN_MULTIPLE_READ_PERIOD == STD_ON)
#if (CAN_MAINFUNCTION_RW_PERIOD_0 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 0.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_0(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_1 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 1.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_1(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_2 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 2.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_2(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_3 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 3.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_3(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_4 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 4.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_4(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_5 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 5.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_5(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_6 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 6.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_6(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_7 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 7.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_7(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_8 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 8.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_8(void);
#endif

#if (CAN_MAINFUNCTION_RW_PERIOD_9 != STD_OFF)
/**
 * @brief Polling of Rx indication at period 9.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Read_9(void);
#endif
#endif /* CAN_MULTIPLE_READ_PERIOD == STD_ON */

/**
 * @brief Polling of bus-off event.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_BusOff(void);

/**
 * @brief Polling of wake-up event.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Wakeup(void);

/**
 * @brief Polling of controller mode transitions.
 * @param none.
 * @return none.
 */
extern FUNC(void, CAN_CODE) Can_MainFunction_Mode(void);

#if defined(AUTOSAR_VERSION_431)
extern Std_ReturnType Can_GetControllerRxErrorCounter (
    uint8 ControllerId,
    uint8 *RxErrorCounterPtr
);

Std_ReturnType Can_GetControllerTxErrorCounter (
    uint8 ControllerId,
    uint8 *TxErrorCounterPtr
);
#endif/*#if defined(AUTOSAR_VERSION_431)*/

#if (VCAN_ENABLE == STD_ON)
VCan_TxRxAbnormalNumType* Can_Vcan_TxRxFifoGetAbnormalNum(uint8 Controller);
#endif/*end of VCAN_ENABLE*/

/**
 * @brief CAN0 interrupt service routine.
 */
ISR(Can_Controller0IrqHandler);
/**
 * @brief CAN1 interrupt service routine.
 */
ISR(Can_Controller1IrqHandler);
/**
 * @brief CAN2 interrupt service routine.
 */
ISR(Can_Controller2IrqHandler);
/**
 * @brief CAN3 interrupt service routine.
 */
ISR(Can_Controller3IrqHandler);
/**
 * @brief CAN4 interrupt service routine.
 */
ISR(Can_Controller4IrqHandler);
/**
 * @brief CAN5 interrupt service routine.
 */
ISR(Can_Controller5IrqHandler);
/**
 * @brief CAN6 interrupt service routine.
 */
ISR(Can_Controller6IrqHandler);
/**
 * @brief CAN7 interrupt service routine.
 */
ISR(Can_Controller7IrqHandler);
/**
 * @brief CAN8 interrupt service routine.
 */
ISR(Can_Controller8IrqHandler);
/**
 * @brief CAN9 interrupt service routine.
 */
ISR(Can_Controller9IrqHandler);
/**
 * @brief CAN10 interrupt service routine.
 */
ISR(Can_Controller10IrqHandler);
/**
 * @brief CAN11 interrupt service routine.
 */
ISR(Can_Controller11IrqHandler);
/**
 * @brief CAN12 interrupt service routine.
 */
ISR(Can_Controller12IrqHandler);
/**
 * @brief CAN13 interrupt service routine.
 */
ISR(Can_Controller13IrqHandler);
/**
 * @brief CAN14 interrupt service routine.
 */
ISR(Can_Controller14IrqHandler);
/**
 * @brief CAN15 interrupt service routine.
 */
ISR(Can_Controller15IrqHandler);

/**
 * @brief VCAN0 interrupt service routine.
 */
ISR(VCan_Controller0IrqHandler);
/**
 * @brief VCAN1 interrupt service routine.
 */
ISR(VCan_Controller1IrqHandler);
/**
 * @brief VCAN2 interrupt service routine.
 */
ISR(VCan_Controller2IrqHandler);
/**
 * @brief VCAN3 interrupt service routine.
 */
ISR(VCan_Controller3IrqHandler);
/**
 * @brief VCAN4 interrupt service routine.
 */
ISR(VCan_Controller4IrqHandler);
/**
 * @brief VCAN5 interrupt service routine.
 */
ISR(VCan_Controller5IrqHandler);
/**
 * @brief VCAN6 interrupt service routine.
 */
ISR(VCan_Controller6IrqHandler);
/**
 * @brief VCAN7 interrupt service routine.
 */
ISR(VCan_Controller7IrqHandler);
/**
 * @brief VCAN8 interrupt service routine.
 */
ISR(VCan_Controller8IrqHandler);
/**
 * @brief VCAN9 interrupt service routine.
 */
ISR(VCan_Controller9IrqHandler);
/**
 * @brief VCAN10 interrupt service routine.
 */
ISR(VCan_Controller10IrqHandler);
/**
 * @brief VCAN11 interrupt service routine.
 */
ISR(VCan_Controller11IrqHandler);
/**
 * @brief VCAN12 interrupt service routine.
 */
ISR(VCan_Controller12IrqHandler);
/**
 * @brief VCAN13 interrupt service routine.
 */
ISR(VCan_Controller13IrqHandler);
/**
 * @brief VCAN14 interrupt service routine.
 */
ISR(VCan_Controller14IrqHandler);
/**
 * @brief VCAN15 interrupt service routine.
 */
ISR(VCan_Controller15IrqHandler);


#ifdef __cplusplus
}
#endif

#endif /* CANH_H_ */
